package cn.appliedata.base.zuul.filter;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;

//import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

import cn.appliedata.base.zuul.constants.ZuulConstants;
//import cn.appliedata.common.ResponseWrapper;
//import cn.appliedata.constants.SessionConstant;
//import cn.appliedata.model.account.UserAccount;
//import cn.appliedata.model.identity.perm.PermDTO;
//import cn.appliedata.model.identity.typeenum.RestType;
import lombok.Getter;
import lombok.Setter;

@RefreshScope
@ConfigurationProperties(prefix="permissionFilter")
public class PermissionFilter extends ZuulFilter {
	@Setter
	@Getter
	/**
	 * 忽略规则
	 */
	private List<Map<String, String>> ignore;
	@Setter
	@Getter
	/**
	 * 校验规则
	 */
	private List<Map<String, String>> check;

	@Override
	public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpSession session = request.getSession();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        //UserAccount loginUser = (UserAccount)session.getAttribute(SessionConstant.SESSION_ACCOUNT_KEY);
		boolean has = false;
		if(check != null && !checkPermArray(uri, method, check)) {
			return null;
		}
        if(ignore != null) {
            has = checkPermArray(uri, method, ignore);
        }
//        if(!has && loginUser != null) {
//        	has = checkPerm(uri, method, loginUser.getPerms());
//        }
//        if(!has && loginUser == null) {
//        	ctx.setSendZuulResponse(false);
//            ctx.setResponseStatusCode(200);
//            ctx.set(ZuulConstants.FILTER_FLAG_KEY, false);
//            ctx.setResponseBody(JSONObject.toJSONString(new ResponseWrapper<>(false, ZuulConstants.MSG_NO_LOGIN)));
//            return null;
//        }
//        else if(!has) {
//            ctx.setSendZuulResponse(false);
//            ctx.setResponseStatusCode(401);
//            ctx.set(ZuulConstants.FILTER_FLAG_KEY, false);
//            ctx.setResponseBody(JSONObject.toJSONString(new ResponseWrapper<>(false, ZuulConstants.MSG_NO_PERM)));
//            return null;
//        }
		return null;
	}
	/**
	 * 判断是否有权限[校验规则/忽略规则]
	 * @param uri
	 * @param method
	 * @param ignore  noLoginPerms
	 * @return
	 */
	private static boolean checkPermArray(String uri, String method, List<Map<String, String>> ignore) {
		return ignore.stream().anyMatch(perm -> {
			if(StringUtils.isBlank(perm.get("uri"))
					|| !uri.matches(perm.get("uri"))) {
				return false;
			}
			if(StringUtils.isNotBlank(perm.get("restType"))
					&& method.toLowerCase().matches(perm.get("restType").toLowerCase())) {
				return true;
			}
			return false;
		});
	}
	/**
	 * 判断是否有权限[权限列表]
	 * @param uri
	 * @param method
	 * @param perms
	 * @return
	 */
	private static boolean checkPerm(String uri, String method, List<?> perms) {
		/*return perms.stream().anyMatch(perm -> {
			if("/api-tool/toolbar/\\d+".equals(perm.getUri())) {
				System.out.println(perm.getUri());
			}
			if(StringUtils.isBlank(perm.getUri())
					|| !uri.matches(perm.getUri())) {
				return false;
			}
			if(StringUtils.isNotBlank(perm.getRestType())
					&& perm.getRestType().equals(String.valueOf(RestType.parse(method.toLowerCase()).getCode()))) {
				return true;
			}
			return false;
		});*/
		return true;
	}

	@Override
	public boolean shouldFilter() {
		RequestContext ctx = RequestContext.getCurrentContext();
		//是否过滤
		return ctx.get(ZuulConstants.FILTER_FLAG_KEY) == null ? true: ctx.getBoolean(ZuulConstants.FILTER_FLAG_KEY);
	}

	@Override
	public int filterOrder() {
		//过滤执行顺序
		return 1;
	}

	@Override
	public String filterType() {
		/*
		pre：路由之前
		routing：路由之时
		post： 路由之后
		error：发送错误调用
		*/
		return FilterConstants.PRE_TYPE;
	}
}
